package com.tianji.learning.delaytask;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;


@Component
@Slf4j
public class RedissonDelayTask {

    @Autowired
    private RedissonClient redissonClient;

    private static final String QUEUE_NAME="queue.delay";

    /*
    *  Redisson实现延迟队列底层通过两种数据结构
    * 中中转队列(ZSet): 这是一个延迟队列，将数据按照延迟时间排序，过期后转移到List
    * 目标队列(List) : 这是一个阻塞队列，按照先进先出规则存放数据，等待消费者获取
    *
    * */
    //生产者:向队列保存内容
    public void setQueue(String value,Integer delay){
        // 设置List
        RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque(QUEUE_NAME);
        // 设置ZSet
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        //向延迟队列存储数据
        delayedQueue.offer(value,delay, TimeUnit.SECONDS);
    }
    //消费者:从队列中获取内容
    @PostConstruct //对象创建完成后会自动执行此方法
    public void getQueue(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 获取List
                RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque(QUEUE_NAME);
                // 持续监听
                while (true) {
                    String value=blockingDeque.poll();
                    if(StrUtil.isNotEmpty(value)){
                        System.out.println(value);
                    }
                }
            }
        }).start();

    }



}
